package com.kcyu.sfhinvoice.service.impl;

import cn.hutool.core.io.file.FileNameUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.kcyu.sfhinvoice.domain.FileDO;
import com.kcyu.sfhinvoice.service.FileService;
import com.kcyu.sfhinvoice.mapper.FileMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

/**
 * @author yujiancong
 * @description 针对表【file(文件)】的数据库操作Service实现
 * @createDate 2024-01-02 11:50:38
 */
@Service
@Slf4j
public class FileServiceImpl extends ServiceImpl<FileMapper, FileDO>
        implements FileService {

    @Value("${file-storage-path}")
    private String filePathBase;

    @Override
    @Transactional
    public FileDO upload(MultipartFile file, String modelCode, String busiKey) {
        FileDO fileDO = new FileDO();
        fileDO.setModelCode(modelCode);
        fileDO.setBusiKey(busiKey);
        fileDO.setFileName(file.getOriginalFilename());
        fileDO.setFileSize(file.getSize());


        System.out.println("filePathBase = " + filePathBase);
        String filename = file.getOriginalFilename();
        // 获取文件扩展名
        String extensionName = filename.substring(filename.lastIndexOf(".") + 1);
        fileDO.setFileType(extensionName);
        // 除去文件扩展名部分
        String fileNameExcludeType = filename.substring(0, filename.lastIndexOf("."));
        // 获取当前时间年月日时分秒字符串
        Date now = new Date();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
        String formattedDate = sdf.format(now);
        String filePath = filePathBase + fileNameExcludeType + formattedDate + "." + extensionName;
        fileDO.setFilePath(filePath);
        this.save(fileDO);

        File dest = new File(filePath);
        if (!dest.getParentFile().exists()) {
            dest.getParentFile().mkdirs();
        }

        // 写入本地
        InputStream inputStream = null;
        try {
            inputStream = file.getInputStream();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        inputStreamToFile(inputStream, dest);


        return fileDO;
    }

    @Override
    public List<FileDO> queryFile(String modelCode, String busiKey) {
        QueryWrapper<FileDO> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(FileDO::getModelCode, modelCode).eq(FileDO::getBusiKey, busiKey);
        return this.baseMapper.selectList(queryWrapper);
    }

    @Override
    public boolean removeFile(String fileId) {
        FileDO fileDO = this.getById(fileId);
        if (fileDO == null) {
            return false;
        }
        String filePath = fileDO.getFilePath();
        File file = new File(filePath);
        if (file.exists()) {
            file.delete();
        }
        return this.removeById(fileId);
    }

    @Override
    public String uploadAsset(MultipartFile file) {
        long time = new Date().getTime();
        String filePath = time + file.getOriginalFilename();
        String fileAllPath = filePathBase + "asset/" + filePath;
        File dest = new File(fileAllPath);
        if (!dest.getParentFile().exists()) {
            dest.getParentFile().mkdirs();
        }

        // 写入本地
        InputStream inputStream = null;
        try {
            inputStream = file.getInputStream();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        inputStreamToFile(inputStream, dest);

        return filePath;
    }

    @Override
    public void getAssets(String filePath, HttpServletResponse response) {
        File file = new File(filePathBase + "asset/" + filePath);
        try {
            FileInputStream fileInputStream = new FileInputStream(file);
            InputStream fis = new BufferedInputStream(fileInputStream);
            byte[] buffer = new byte[fis.available()];
            fis.read(buffer);
            fis.close();
            // 清空response
            response.reset();
            // 设置response的Header
            response.setCharacterEncoding("UTF-8");
            response.addHeader("Content-Disposition", "inline;filename=" + URLEncoder.encode(filePath, "UTF-8"));
            response.setContentType("application/octet-stream");

            // 告知浏览器文件的大小
            response.addHeader("Content-Length", "" + file.length());
            OutputStream outputStream = new BufferedOutputStream(response.getOutputStream());
            outputStream.write(buffer);
            outputStream.flush();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 流写入文件
     *
     * @param inputStream 文件输入流
     * @param file        输出文件
     */
    private static void inputStreamToFile(InputStream inputStream, File file) {
        try {
            OutputStream os = new FileOutputStream(file);
            int bytesRead = 0;
            byte[] buffer = new byte[8192];
            while ((bytesRead = inputStream.read(buffer, 0, 8192)) != -1) {
                os.write(buffer, 0, bytesRead);
            }
            os.close();
            inputStream.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}




